#include <fstream>
#include <algorithm>

namespace AirlineRes
{

template <class RecordType>
int RecordManager<RecordType>::LoadRecords( std::string const& _filePath )
{
  // Open the file.
  std::ifstream file( _filePath, std::ifstream::in );
  if ( !file.good() )
  {
    std::cerr << "Failure opening file: \"" << _filePath << "\"\n";
    return 1;
  }

  RecordType r;

  while ( !file.eof() )
  {
    Record::RecordIOResult res = r.LoadRecord( file );
    m_records.insert( r );


    if ( res != Record::RecordIOResult_Success )
    {
      file.close();
      std::cerr << "Failure reading file: \"" << _filePath << "\"\n";
      return 1;
    }
  }

  file.close();

  UpdateMaxID();

  return 0;
}

template <class RecordType>
int RecordManager<RecordType>::WriteRecords( std::string const& _filePath )
{
  // Open the file.
  std::ofstream file( _filePath, std::ofstream::out );
  if ( !file.good() )
  {
    std::cerr << "Failure opening file: \"" << _filePath << "\"\n";
    return 1;
  }

  for ( auto it = m_records.begin(); it != m_records.end(); ++it )
  {
    it->WriteRecord( file );
  }

  file.close();
  return 0;
}

template <class RecordType>
int RecordManager<RecordType>::PrintRecords( std::ostream& _stream )
{
  for ( auto it = m_records.begin(); it != m_records.end(); ++it )
  {
    it->WriteRecord( _stream );
  }
  return 0;
}

template <class RecordType>
RecordType const* RecordManager<RecordType>::GetRecord( int _id ) const
{
  auto it = std::find_if(
              m_records.begin(),
              m_records.end(),
              [_id](RecordType _a){ return _a.GetID() == _id; }
            );

  if ( it != m_records.end() )
  {
    return &(*it);
  } else {
    return NULL;
  }
}

template <class RecordType>
int RecordManager<RecordType>::AddRecord( RecordType const& _record )
{
  RecordType r( _record );
  r.m_id = ++m_maxID;
  m_records.insert( r );
  return 0;
}

template <class RecordType>
int RecordManager<RecordType>::EditRecord( RecordType const& _record )
{
  int ret = DeleteRecord( _record.GetID() );
  if ( !ret ) {
    m_records.insert( _record );
    return 0;
  } else {
    return ret;
  }
}

template <class RecordType>
int RecordManager<RecordType>::DeleteRecord( int _id )
{
  //auto IsEqual = ;

  auto it = std::find_if(
              m_records.begin(),
              m_records.end(),
              [_id](RecordType _a){ return _a.GetID() == _id; }
            );

  m_records.erase( it );
  
  return 0;
}

template <class RecordType>
void RecordManager<RecordType>::UpdateMaxID()
{
  auto pr = [](RecordType const& _a, RecordType const& _b){ return _a.GetID() < _b.GetID(); };
  m_maxID = std::max_element( m_records.begin(), m_records.end(), pr )->GetID();
}

}